home *** CD-ROM | disk | FTP | other *** search
- ; June 19, 1995
- ; This program is a pair of subroutines I use to generate random
- ; number is assembly langauge. The first subroutine is called at
- ; the start of the program to initialize the seeds to unique values.
- ; This is done using the currenttime function of intuition. Thus,
- ; S2 which is set to the microseconds value has a 1 in 1,000,000
- ; chance of starting at the same value as any given previous run.
- ; S1 should always be unique.
- ; The second subroutine is based on the algorithm of Pierre L'Ecuyer
- ; [L'Ecuyer, P. Efficient and Portable Combined Random Number Generators.
- ; _Commun._ASM_31_, 6 (June, 1988) 742]. Please see the original
- ; article for a detailed explanation.
- ;
- ; These programs were written to be used by any 68000 type processor
- ; and can be assembled using the a68k assembler. They can be incorp-
- ; orated into programs directly or by linking the object code if
- ; setseed, randnum, intubase, and mathbase are xdef'ed in this routine
- ; and xref'ed in the main program.
- ; Distribution: These routines are intended as freeware and their
- ; distribution is restricted as follows:
- ;
- ; Source code: The source code must be accompanied by all comments
- ; include the introductory comments and the program comments.
- ; No fee may be charged for distribution of the code.
- ; Executable code: The executable version of these routines may be used if:
- ; 1) The documentation of the main program includes the
- ; following text:
- ; "This program uses the L'Ecuyer random number generator
- ; as written for the amiga by Scott McMahan."
- ; 2) The main program using these routines is either freeware
- ; or the author(s) have the express, written consent of me,
- ; Scott McMahan.
- ; (No big deal here, I just don't want to pay for shareware
- ; that uses my routine. Permission will be easy to get.)
- ;
- ;To contact the author and/or make bug reports, mail me at
- ; Scott McMahan
- ; 2538 Fairfield Pl #1
- ; Madison, WI 53704
- ; Sorry, no Email because I expect my email address to be changing in
- ; the next 6 months and then again in the next 2 years.
-
- CurrentTime equ -$0054
- IEEEDPFlt equ -$0024
- IEEEDPDiv equ -$0054
-
- ;Routine to set up S1 and S2 (seeds for random number generator)
- ;based on currenttime function
- ;parameters: none
- ;presets: intubase= base address of
- ; intuition.library
- ; CurrentTime= offset for currenttime
- ; function of intuition
- ;returns: none
- ;changed regs/mem locations: none/S1,S2
- section text,code
- xdef @setseed
- @setseed:
- ; movem.l A0/A1,-(A7) ;save registers ******
- lea S1(A4),A0 ;get the current seconds and
- lea S2(A4),A1 ;microseconds as seeds
- move.l _IntuitionBase(A4),A6
- jsr CurrentTime(A6) ;in S1 and S2
- addq.l #1,S1(A4) ;add one to S1 and S2 to make sure greater than 0
- addq.l #1,S2(A4)
- cmpi.l #$7FFFFFAA,S1(A4) ;make sure S1<=2147483562
- ble.S 20$
- subi.l #$7FFFFFAA,S1(A4)
- 20$ cmpi.l #$7FFFFF06,S2(A4) ;make sure S2<=2147483398
- ble.S 30$
- subi.l #$7FFFFF06,S2(A4)
- 30$ ; movem.l (A7)+,A0/A1 ******
- rts
-
- ;Routine to generate a random number from 0 to 1
- ;using S1 and S2 as seeds
- ;Parameters: S1 and S2 Seeds
- ;presets mathbase = base address of
- ; mathieeedoubbas.library
- ; IEEEDPFlt= Offset of int to IEEE
- ; routine
- ; IEEEDPDiv= Offset of IEEE division
- ; routine
- ;Returns: D0/D1 = Random number from 0 to 1
- ; in IEEE double precision
- ;Changed regs/mem locations D0,D1/S1,S2
-
- xdef @random
- ; section rand,code ******
- @random movem.l D2/D3/A6,-(A7)
- move.l S1(A4),D1
- divu #$D1A4,D1 ;D1=S1 DIV 53668 (k in article)
- move.l D1,D0 ;D0 also equals k
- swap D1
- mulu #$9C4E,D1 ;D1=40014*(S1-k*53668)
- mulu #$2FB3,D0 ;D0=12211*k
- sub.l D0,D1 ;D1=40014*(S1-k*53668)-12211*k
- ; tst.l D1 ******
- bgt.S 20$ ;if D1<1
- add.l #$7FFFFFAB,D1 ;then D1=D1+2147483563
- 20$ move.l D1,S1(A4) ;store D2 in S1 as new seed
- move.l S2(A4),D1
- divu #$CE26,D1 ;D1=S2 DIV 52774 (k in article)
- move.l D1,D0 ;D0 also equals k
- swap D1
- mulu #$9EF4,D1 ;D1=40692*(S1-k*52774)
- mulu #$0ECF,D0 ;D0=3791*k
- sub.l D0,D1 ;D1=40692*(S1-k*52774)-3791*k
- ; tst.l D1
- bgt.S 30$ ;if D1<1
- add.l #$7FFFFF07,D1 ;then D1=D1+2147483399
- 30$ move.l D1,S2(A4) ;store D2 in S2 as new seed
- move.l S1(A4),D0
- sub.l S2(A4),D0 ;D0=S1-S2
- ; tst.l D0 ******
- bge.S 40$ ;if D0<0
- add.l #$7FFFFFA9,D0 ;then D0=D0+2147483562
- 40$ move.l _MathIeeeDoubBasBase(A4),A6
- jsr IEEEDPFlt(A6) ;convert it to IEEE Double Precision
- move.l #$41DFFFFF,D2 ;
- move.l #$EA800000,D3 ;
- jsr IEEEDPDiv(A6) ;Divide it by 2147483562
- movem.l (A7)+,D2/D3/A6
- rts
-
- section __MERGED,BSS
- ; even ******
- xref _IntuitionBase
- xref _MathIeeeDoubBasBase
-
- S1: ds.l 1 ;first seed for generator, set to seconds by
- ;currenttime
- S2: ds.l 1 ;second seed for generator, set to microsecs
- ;by currenttime
- end
-